package com.quanyan.sms.service.impl;

import com.quanyan.common.constants.Constants;
import com.quanyan.common.utils.RandomStringGenerator;
import com.quanyan.redisCluster.utils.RedisConstants;
import com.quanyan.redisCluster.utils.RedisKey;
import com.quanyan.sms.cache.SmsRedisTemplate;
import com.quanyan.sms.entity.TbSmsContent;
import com.quanyan.sms.mapper.TbSmsContentMapper;
import com.quanyan.sms.service.SmsService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sms.SmsApi;
import sms.impl.ChuangLanSms;
import sms.impl.HuyiSms;
import sms.model.Result;

/**
 * Created by yangyun on 16-6-21.
 */
@Service("smsService")
public class SmsServiceImpl implements SmsService {
    private Logger logger = LoggerFactory.getLogger(getClass());

    private String REDIS_USER_PHONE_CODE_SET = "user_phone_code_set_";
    private String REDIS_USER_PHONE_MESSAGE_RESEND = "user_phone_message_resend";

    @Autowired
    private TbSmsContentMapper tbSmsContentMapper;

    @Autowired
    private SmsRedisTemplate smsCache;

    @Override
    public Result sendMessageToPhone(String phone, Byte templateId, String[] args, boolean failResend) {

        logger.warn("====  recieve send msg {} to phone {}", JSONArray.fromObject(args), phone);
        TbSmsContent tbSmsContent = new TbSmsContent();
        tbSmsContent.setPhone(phone);

        JSONObject object = new JSONObject();
        object.element("templateId", templateId);
        object.element("args", JSONArray.fromObject(args));
        tbSmsContent.setContent(object.toString());
        tbSmsContent.setState(Constants.NO);
//        this.tbSmsContentMapper.insertSelective(tbSmsContent);

        SmsApi smsApi = new HuyiSms();
        Result result = smsApi.sendMsg(phone, templateId, args);
        //logger.info("--------send----message------------------->" + result.isStatus());
        if (!result.isStatus()) {
            smsApi = new ChuangLanSms();
            result = smsApi.sendMsg(phone, templateId, args);
            //logger.info("-------send----message2-------------------->" + result.isStatus());
        }
        if (result != null && result.isStatus()) {
            TbSmsContent smsContent = new TbSmsContent();
            smsContent.setId(tbSmsContent.getId());
            smsContent.setState(Constants.YES);
//            this.tbSmsContentMapper.updateByPrimaryKeySelective(tbSmsContent);
        }
        return result;
    }

    /**
     * 发送验证码
     *
     * @param phone      目标手机
     * @param templateId 模板id
     * @param resend     重发时间
     * @param exp        过期时间
     * @return
     */
    public Result sendValidCodetToPhone(String phone, Byte templateId, int resend, int exp) {
        //判断验证码是否过期.
        logger.info("1、开始获取该手机号是否存在已发送验证码；时间：【{}】",System.currentTimeMillis());
        String code = (String) smsCache.get(RedisConstants.SMS_FAMILY_KEY + REDIS_USER_PHONE_MESSAGE_RESEND + templateId + phone);
        logger.info("2、查看通过该手机号获取的验证码：{}；时间：【{}】",code,System.currentTimeMillis());
        if (code == null) {
            logger.info("3、开始生成验证码；时间：【{}】",System.currentTimeMillis());
            code = RandomStringGenerator.getRandomDigitByLength(4);
            logger.info("4、生成验证码为：【{}】；时间：【{}】",code,System.currentTimeMillis());
            //您的验证码是：【变量】，【变量】分钟内有效，短信编号【变量】。
            Result result = sendMessageToPhone(phone, templateId, new String[]{code, (exp / 60) + ""}, false); // TODO
            logger.info("5、发送验证码返回情况：【{}】；时间：【{}】",result.getCode(),System.currentTimeMillis());
            result.setContent(code);
            logger.info("6、发送验证码返回状态：【{}】；时间：【{}】",result.isStatus(),System.currentTimeMillis());
            if (result.isStatus()) {
                logger.info("7、开始将数据存入redis：【{}】；时间：【{}】",RedisConstants.SMS_FAMILY_KEY + REDIS_USER_PHONE_CODE_SET + templateId + phone,System.currentTimeMillis());
                smsCache.zadd(RedisConstants.SMS_FAMILY_KEY + REDIS_USER_PHONE_CODE_SET + templateId + phone, System.currentTimeMillis() + (exp * 1000), code);
                logger.info("8、数据存入redis成功，开始保存保存存储信息：【{}】；时间：【{}】",RedisConstants.SMS_FAMILY_KEY + REDIS_USER_PHONE_MESSAGE_RESEND + templateId + phone,System.currentTimeMillis());
                smsCache.save(RedisConstants.SMS_FAMILY_KEY + REDIS_USER_PHONE_MESSAGE_RESEND + templateId + phone, code, resend);
                logger.info("9、redis存入成功；时间：【{}】",System.currentTimeMillis());
            }
            logger.info("10、result最终状态【{}】；时间：【{}】",result.getMsg(),System.currentTimeMillis());
            return result;
        } else {
            return Result.returnFail(Result.SMS_SEND_TOO_OFTEN);
        }
    }

    /**
     * 校验验证码
     *
     * @param phone
     * @param templateId
     * @param code
     * @return
     */
    public boolean verifyValidCode(String phone, Byte templateId, String code) {
        RedisKey redisKey = new RedisKey(RedisConstants.SMS_FAMILY_KEY, REDIS_USER_PHONE_CODE_SET + templateId + phone);
        double score = smsCache.zScore(redisKey.getRedisKey(), code);
        if (score == 0.0) {
            logger.warn("verifyValidCode failed, code is not found, phone:" + phone + ",code:" + code);
            return false;
        }
        if ((long) score >= System.currentTimeMillis()) {
            smsCache.delteKey(redisKey);
            smsCache.delteKey(new RedisKey(RedisConstants.SMS_FAMILY_KEY, REDIS_USER_PHONE_MESSAGE_RESEND + templateId + phone));
            return true;
        }
        logger.warn("verifyValidCode failed, code expired,phone:" + phone + ",code:" + code + ",score:" + score);
        return false;
    }
}
